﻿using FreeRedis;
using Newtonsoft.Json;

namespace CTP.CRM.Core.Redis
{
    public static class RedisHelper
    {
        private static readonly object _lock = new object();

        private static RedisClient _client;

        private static ConnectionStringBuilder Options;

        public static RedisClient Client => _client;

        internal static void Init(ConnectionStringBuilder options, bool showLogInfo)
        {
            Options = options;
            if (_client != null)
            {
                return;
            }

            lock (_lock)
            {
                if (_client != null)
                {
                    return;
                }

                _client = new RedisClient(options);
                _client.Serialize = (obj) => JsonConvert.SerializeObject(obj);
                _client.Deserialize = (json, type) => JsonConvert.DeserializeObject(json, type);
                if (showLogInfo)
                {
                    _client.Notice += delegate (object? s, NoticeEventArgs e)
                    {
                        Console.WriteLine(Environment.NewLine + e.Log);
                    };
                }
            }
        }

        public static RedisClient Create(Action<ConnectionStringBuilder> action, EventHandler<NoticeEventArgs> notice)
        {
            ConnectionStringBuilder connectionStringBuilder = new ConnectionStringBuilder
            {
                Database = Options.Database,
                ExitAutoDisposePool = Options.ExitAutoDisposePool,
                ClientName = Options.ClientName,
                ConnectTimeout = Options.ConnectTimeout,
                Encoding = Options.Encoding,
                Host = Options.Host,
                IdleTimeout = Options.IdleTimeout,
                MaxPoolSize = Options.MaxPoolSize,
                MinPoolSize = Options.MinPoolSize,
                Password = Options.Password,
                Prefix = Options.Prefix,
                Protocol = Options.Protocol,
                ReceiveTimeout = Options.ReceiveTimeout,
                Retry = Options.Retry,
                SendTimeout = Options.SendTimeout,
                Ssl = Options.Ssl,
                SubscribeReadbytes = Options.SubscribeReadbytes,
                User = Options.User
            };
            action?.Invoke(connectionStringBuilder);
            RedisClient redisClient = new RedisClient(connectionStringBuilder);
            redisClient.Serialize = (obj) => JsonConvert.SerializeObject(obj);
            redisClient.Deserialize = (json, type) => JsonConvert.DeserializeObject(json, type);
            redisClient.Notice += notice;
            return redisClient;
        }

        public static ConnectionStringBuilder BuildConnectionString(Action<ConnectionStringBuilder> action)
        {
            ConnectionStringBuilder connectionStringBuilder = new ConnectionStringBuilder
            {
                Database = Options.Database,
                ExitAutoDisposePool = Options.ExitAutoDisposePool,
                ClientName = Options.ClientName,
                ConnectTimeout = Options.ConnectTimeout,
                Encoding = Options.Encoding,
                Host = Options.Host,
                IdleTimeout = Options.IdleTimeout,
                MaxPoolSize = Options.MaxPoolSize,
                MinPoolSize = Options.MinPoolSize,
                Password = Options.Password,
                Prefix = Options.Prefix,
                Protocol = Options.Protocol,
                ReceiveTimeout = Options.ReceiveTimeout,
                Retry = Options.Retry,
                SendTimeout = Options.SendTimeout,
                Ssl = Options.Ssl,
                SubscribeReadbytes = Options.SubscribeReadbytes,
                User = Options.User
            };
            action?.Invoke(connectionStringBuilder);
            return connectionStringBuilder;
        }
    }
}
